#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/projdefs.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

#include "power_control.h"
#include "RCS_btn.h"

#define POWER_PIN 10

static const char *TAG = "PWR";
static QueueHandle_t igniteQueue;
static power_flow_t power_state = pwr_pre_up;

/**
 * @brief: 在按钮初始化以后调用此函数，先是手动保持按钮按下来供电，保持2s，同时正在执行delay_ms。
 *          2s，以后，在此程序 将引脚拉高，保证供电，可以松开按钮
 * @param  {*}
 * @return {*}
 * @Author: TzzzT
 * @Date: 2022-05-11 19:25:21
 * @LastEditTime: Do not edit
 * @LastEditors: Shadow
 */
void power_init(void)
{
  gpio_reset_pin(POWER_PIN);
  gpio_set_direction(POWER_PIN, GPIO_MODE_INPUT_OUTPUT);
  gpio_set_level(POWER_PIN, true);
}
void power_off(void)
{
  gpio_set_level(POWER_PIN, false);
}

uint8_t is_in_download_ota(void)
{
  return 0;
}

void to_next_state(power_flow_t state)
{
  power_state = state;
}

power_flow_t get_power_state(void)
{
  return power_state;
}

void send_powerdown_event(void)
{
  uint8_t powerdown_signal = 1;
  if (xQueueSend(igniteQueue, &powerdown_signal, pdMS_TO_TICKS(200)) != pdPASS)
  {
    ESP_LOGE(TAG, "igniteQueue full.");
  }
}

// 未完成，短按只发送信息，是否下电应该在这里判断
static void power_control_task(void *arg)
{
  BaseType_t xStatus;
  uint8_t powerdown_signal = 0;
  igniteQueue = xQueueCreate(1, sizeof(uint8_t));
  ESP_LOGI(TAG, "power_control_task Startup..");

  while (1)
  {
    switch (power_state)
    {
    case pwr_pre_up:
    {
      power_init();
      vTaskDelay(pdMS_TO_TICKS(5000));
      register_btn();
      to_next_state(pwr_normal_running);
      ESP_LOGI(TAG, "pwr_pre_up end , goto pwr_normal_running");
      break;
    }
    case pwr_normal_running:
    {
      xStatus = xQueueReceive(igniteQueue, &powerdown_signal, pdMS_TO_TICKS(2000));
      if (xStatus == pdPASS)
      {
        if (powerdown_signal == 1)
        {
          to_next_state(pwr_down_start);
          ESP_LOGI(TAG, "get power down signal, goto pwr_down_start");
        }
      }
      break;
    }
    case pwr_down_start:
    {
      if (is_in_download_ota())
      {
        ESP_LOGI(TAG, "is_in_download_ota");
        vTaskDelay(pdMS_TO_TICKS(2000));
      }
      else
      {
        to_next_state(pwr_down_end);
        ESP_LOGI(TAG, "goto pwr_down_end");
      }
      break;
    }
    case pwr_down_end:
    {
      ESP_LOGI(TAG, "power down");
      power_off();
      vTaskDelay(pdMS_TO_TICKS(1000));
    }
    default:
      break;
    }
  }
  ESP_LOGE(TAG, "out of power control task, delete self");
  vTaskDelete(NULL);
  return;
}

void start_power_control(uint8_t prio)
{
  xTaskCreate(power_control_task, "pwr_ctrl", 2048 * 1, NULL, prio, NULL);
}
